
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#include <SDL/SDL.h>

#include "types.h"
#include "hvl_replay.h"
#include "render.h"
#include "shapes.h"
#include "text.h"

#define FREQ 44100
#define HIVELY_LEN FREQ/50
#define OUTPUT_LEN 4096

extern int part;
extern Uint8 tempdata[];

SDL_Surface *screen;
int ctune = 0;
int dragger=0, enddragger, dragx, dragy;
int wdragger=0;
int paused=0;

char *tunes[] = { "tunes/syphus-sweeties.hvl",
                  "tunes/Virgill-Forsaken.hvl",
                  "tunes/syphus-freeside_run.hvl",
                  "tunes/lb-peanuts.hvl",
                  "tunes/galactic_emeralds.hvl",
                  "tunes/joey_splif-pantsomime.hvl",
                  "tunes/testing123.hvl",
                  "tunes/m0d_-_incognito_crust.hvl" };

int16 hivelyLeft[HIVELY_LEN], hivelyRight[HIVELY_LEN];
size_t hivelyIndex=0;
struct hvl_tune *tune = NULL;

#ifndef DEFAULT_WIDTH
#define DEFAULT_WIDTH 640
#endif

#ifndef DEFAULT_HEIGHT
#define DEFAULT_HEIGHT 480
#endif

int sw=DEFAULT_WIDTH, sh=DEFAULT_HEIGHT;

int clicked, clickx, clicky;

void do_the_music( void *dummy, int8 *stream, int length )
{
  int16 *out;
  int i;
  size_t streamPos = 0;
  length = length >> 1;

  if(tune)
  {
    // Mix to 16bit interleaved stereo
    out = (int16*) stream;
    // Flush remains of previous frame
    for(i = hivelyIndex; i < (HIVELY_LEN); i++)
    {
      out[streamPos++] = hivelyLeft[i];
      out[streamPos++] = hivelyRight[i];
    }

    while(streamPos < length)
    {
      hvl_DecodeFrame( tune, (int8 *) hivelyLeft, (int8 *) hivelyRight, 2 );
      for(i = 0; i < (HIVELY_LEN) && streamPos < length; i++)
      {
        out[streamPos++] = hivelyLeft[i];
        out[streamPos++] = hivelyRight[i];
      }
    }
    hivelyIndex = i;
  }
}

int start_tune( int n )
{
  SDL_PauseAudio( 1 );
  if( tune ) hvl_FreeTune( tune );
  tune = NULL;

  if( n == 8 )
  {
    tune = hvl_reset( (uint8 *)tempdata, 1388, 4, FREQ, 0 );
    if( !tune ) n = ctune;
  }

  if( !tune )
    tune = hvl_LoadTune( tunes[n], FREQ, 4 );

  if( !tune )
  {
    printf( "Couldn't load '%s'!!!11111one\n", tunes[n] );
    return 0;
  }
  hvl_InitSubsong( tune, 0 );
  SDL_PauseAudio( 0 );

  ctune = n;
  return 1;
}

void death( void )
{
  SDL_Quit();
  if( tune ) hvl_FreeTune( tune );
  text_shut();
  shapes_shut();
  render_shut();
}

int isnum( char c )
{
  if( ( c >= '0' ) && ( c <= '9' ) ) return 1;
  return 0;
}


int main( int argc, char *argv[] )
{
  int i, flags;  
  int done, needrender;
  SDL_AudioSpec wanted;
  void *timer;

#ifndef __FIXED_RES__
  int j, k;
#endif

  srand( time( 0 ) );

  if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER ) < 0 )
  {
    printf( "SDL says: %s\n", SDL_GetError() );
    return 0;
  }
  atexit( death );
  
#ifdef __SW_SURFACE__
  flags = SDL_SWSURFACE|SDL_FULLSCREEN;
#else
  #ifdef __HW_ONLY_WINDOWED__
    flags = SDL_SWSURFACE|SDL_FULLSCREEN;
  #else
    flags = SDL_HWSURFACE|SDL_FULLSCREEN|SDL_DOUBLEBUF;
  #endif
#endif

  for( i=1; i<argc; i++ )
  {
    if( argv[i][0] == '-' )
    {
      switch( argv[i][1] )
      {
#ifndef __FULLSCREEN_ONLY__
        case 'w':
          flags &= ~SDL_FULLSCREEN;
#ifdef __HW_ONLY_WINDOWED__
          flags &= ~SDL_SWSURFACE;
          flags |= SDL_HWSURFACE;
#endif // __HW_ONLY_WINDOWED__
          break;
#endif // __FULLSCREEN_ONLY__
        
#ifndef __FIXED_RES__
        case 'r':
          k = 2;
          if( isnum( argv[i][k] ) )
          {
            j = atoi( &argv[i][k] );
            while( isnum( argv[i][k] ) ) k++;
            if( argv[i][k] != 'x' )
            {
              printf( "You need to specify resolution like -r640x480 or so\n" );
              break;
            }
            k++;
            sw = j;
            sh = atoi( &argv[i][k] );
            if( sw < 320 ) sw = 320;
            if( sh < 240 ) sh = 240;
          } else {
            printf( "You need to specify resolution like -r640x480 or so\n" );
            break;
          }
          break;
#endif
      }
    }
  }
  
  screen = SDL_SetVideoMode( sw, sh, 16, flags );
  if( !screen )
  {
    printf( "SDL says: %s\n", SDL_GetError() );
    return 0;
  }
  
  SDL_WM_SetCaption( "Planet Hively", 0 );
  SDL_ShowCursor( SDL_DISABLE );
  
  if( !render_init() ) return 0;
  if( !shapes_init() ) return 0;
  if( !text_init() ) return 0;

  wanted.freq = FREQ; 
  wanted.format = AUDIO_S16SYS; 
  wanted.channels = 2; /* 1 = mono, 2 = stereo */
  wanted.samples = OUTPUT_LEN; // HIVELY_LEN;

  wanted.callback = (void*)do_the_music;
  wanted.userdata = 0;

  if( SDL_OpenAudio( &wanted, NULL ) < 0 )
  {
    printf( "SDL says: %s\n", SDL_GetError() );
    return 0;
  }
  
  timer = SDL_AddTimer( FPSTIME, timing, 0 );

  hvl_InitReplayer();

  if( start_tune( 0 ) == 0 )
    return 0;
    
  done = 0;
  needrender = 0;
  while( !done )
  {
    SDL_Event event;
    
    SDL_WaitEvent( &event );
    do {
      switch( event.type )
      {
        case SDL_MOUSEMOTION:
          dragx = event.motion.x;
          dragy = event.motion.y;
          break;
            
        case SDL_MOUSEBUTTONUP:
          if( event.button.button == SDL_BUTTON_LEFT )
            enddragger = 1;
          break;

        case SDL_MOUSEBUTTONDOWN:
          if( event.button.button == SDL_BUTTON_LEFT )
          {
            clickx = event.button.x;
            clicky = event.button.y;
            if(( clickx >= 0 ) && ( clickx < sw ) && ( clicky >= 0 ) && ( clicky < sh ))
              clicked = 1;
          }
          enddragger = 0;
          break;
        
        case SDL_KEYDOWN:
          switch( event.key.keysym.sym )
          {
            case 'f':
            case 'F':
            case SDLK_RETURN:	// was going to use alt-return, but since return isn't doing anything else..
              SDL_WM_ToggleFullScreen( screen );
              break;

            case 'p':
            case 'P':
              paused ^= 1;
              SDL_PauseAudio( paused );
              break;

            case SDLK_ESCAPE:
//              if( part == PART_MAIN )
//                fade_in( "click the sun to exit!", 1 );
//              else
              done = 1;
              break;
            
            default:
              break;
          }
          break;
        
        case SDL_QUIT:
//          if( part == PART_MAIN )
//            fade_in( "click the sun to exit!", 1 );
//          else
          done = 1;
          break;
        
        case SDL_USEREVENT:
          needrender = 1;
          break;
      }
    } while( SDL_PollEvent( &event ) );
    
    if( needrender )
    {
      needrender = 0;
      done |= render();
    }
  }
  
  SDL_PauseAudio( 1 );
  return 0;
}
